

package Tabler;

use FileHandle;

sub new {
    my $level = 0;
    my $pkg = shift;
    
    $level = shift if @_ > 0 ;
    return bless { level => $level, lineheads => undef, names => undef, bodies => undef, footers => undef, broken_flags => undef }, $pkg;
}

sub add {
    my $self = shift;
    my $linehead = shift;
    my $name = shift;
    my $body = shift;
    my $footer = undef;
    
    $footer = shift;

    push @{$self->{lineheads}}, $linehead;
    push @{$self->{names}}, $name;
    push @{$self->{bodies}}, $body;
    push @{$self->{footers}}, $footer;
    push @{$self->{broken_flags}}, 0;
}

sub add_title {
    my $self = shift;
    my $linehead = shift;
    my $name = shift;
    my $footer = undef;
    
    $footer = shift;

    push @{$self->{lineheads}}, $linehead;
    push @{$self->{names}}, $name;
    push @{$self->{bodies}}, "";
    push @{$self->{footers}}, $footer;
    push @{$self->{broken_flags}}, 1;
}

sub print {
    my $self = shift;
    my $fh = STDOUT;
    my $linehead_max = 0;
    my $name_max = 0;
    my $v;
    my $sp;

    $fh = shift if @_ > 0 ;

    for $v ( @{$self->{lineheads}} ) {
	$linehead_max = length($v) if length($v) > $linehead_max;
    }
    for $v ( 0 .. @{$self->{names}}-1 ) {
	if ( !${$self->{broken_flags}}[$v] ) {
	    $name_max = length(${$self->{names}}[$v]) if length(${$self->{names}}[$v]) > $name_max;
	}
    }

    while ( @{$self->{lineheads}} || @{$self->{names}} || @{$self->{bodies}} || @{$self->{footers}} ) {
	$v = shift(@{$self->{lineheads}});
	print $fh $v;
	print $fh " " x ($linehead_max - length($v) + 1 + 2 * $self->{level});
	$v = shift(@{$self->{names}});
	print $fh $v;
	$sp = $name_max - length($v);
	$v = shift(@{$self->{bodies}});
	if ( !shift(@{$self->{broken_flags}}) && defined($v) ) { 
	    print $fh " " x $sp;
	    print $fh $v;
	}
	print $fh "\n";
	$v = shift(@{$self->{footers}});
	if ( defined $v ) {
	    $v->set_level($self->{level} + 1);
	    $v->print($fh);
	}
    }
}

sub set_level {
    my $self = shift;
    my $level = 0;
    
    $level = shift if @_ > 0 ;
    $self->{level} = $level;
}
    
1;
